package com.lx.yygh.api;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lx.yygh.common.exception.YyghException;
import com.lx.yygh.common.helper.HttpClientUtils;
import com.lx.yygh.common.helper.JwtHelper;
import com.lx.yygh.common.result.Result;
import com.lx.yygh.common.result.ResultCodeEnum;
import com.lx.yygh.common.util.HttpUtil;
import com.lx.yygh.model.user.UserInfo;
import com.lx.yygh.service.UserInfoService;
import com.lx.yygh.utils.ConstantPropertiesUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * @author c先生
 * @date 2022年10月24日 下午 5:16:21
 * @describe
 */
@Api("微信操作的接口")
@Controller
@RequestMapping("/api/ucenter/wx/")
public class WxApiController {

    @Resource
    UserInfoService userInfoService;

    @ApiOperation(value = "返回生成微信二维码所需要的参数")
    @GetMapping("/getLoginParam")
    @ResponseBody
    public Result getLoginParam(){
        Map<String,String> map = new HashMap<>();
        map.put("appid",ConstantPropertiesUtil.WX_OPEN_APP_ID);
        map.put("scope","snsapi_login");
        //重定向地址，需要进行UrlEncode
        String redirectUrl = null;
        try {
            redirectUrl = URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL,"utf-8");
        } catch (UnsupportedEncodingException e) {
            //url编码异常
            new YyghException(ResultCodeEnum.URL_ENCODE_ERROR).printStackTrace();
        }
        map.put("redirectUri",redirectUrl);
        map.put("state", String.valueOf(System.currentTimeMillis()));
        return Result.ok(map);
    }

    @ApiOperation(value = "微信登录的回调函数")
    @GetMapping("/callback")
    public String callback(String code,String state){
        //验证返回值是否为空
        if(!(StringUtils.hasText(code)&&StringUtils.hasText(state))){
            //两个至少有一个为空，抛出异常
            throw new YyghException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);//非法回调请求
        }

        /*
         ==其中的%s是stringBuffer的占位符==
        StringBuffer sb = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token?")
                .append("appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String format = String.format(sb.toString(), ConstantPropertiesUtil.WX_OPEN_APP_ID, ConstantPropertiesUtil.WX_OPEN_APP_SECRET, code);
        */

        //通过code获取access_token,使用HTTPClient工具类发送请求
        //拼装url  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        String accessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token?")
                .append("appid=").append(ConstantPropertiesUtil.WX_OPEN_APP_ID)
                .append("&secret=").append(ConstantPropertiesUtil.WX_OPEN_APP_SECRET)
                .append("&code=").append(code)
                .append("&grant_type=").append("authorization_code")
                .toString();
        String result = null;
        try {
            result = HttpClientUtils.get(accessTokenUrl);
        } catch (Exception e) {
            new YyghException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD).printStackTrace();//获取token失败
        }
        //把返回的结果从字符串转化为Json对象
        JSONObject jsonObjectResult = JSONObject.parseObject(result);
        //验证返回的结果
        if(StringUtils.hasText(jsonObjectResult.getString("errcode"))){
            //说明错误码不为空，说明返回的结果有误，那么抛出异常
            throw new YyghException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);//获取token失败
        }
        //从json对象中得到accessToken
        String accessToken = jsonObjectResult.getString("access_token");

        //获取用户个人信息
        //验证数据库中是否存在此用户（根据openId来判断）
        String openid = jsonObjectResult.getString("openid");
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("openid",openid);
        UserInfo userInfo = userInfoService.getOne(wrapper);
        if(null==userInfo){
            userInfo = new UserInfo();
            //数据库中不存在此用户，此用户为第一次登录系统，获取用户信息，存入数据库
            //userInfo = new UserInfo();
            //根据accessToken获取用户个人信息  https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
            String getUserInfoUrl = new StringBuffer()
                    .append("https://api.weixin.qq.com/sns/userinfo?")
                    .append("access_token=").append(accessToken)
                    .append("&openid=").append(openid)
                    .toString();
            String result4UserInfo = null;
            try {
                result4UserInfo = HttpClientUtils.get(getUserInfoUrl);
            } catch (Exception e) {
                new YyghException(ResultCodeEnum.FETCH_USERINFO_ERROR).printStackTrace();//获取用户信息失败
                e.printStackTrace();
            }
            //把结果转发为json对象
            JSONObject jsonObjectUserInfo = JSONObject.parseObject(result4UserInfo);
            //验证返回的结果
            if(StringUtils.hasText(jsonObjectResult.getString("errcode"))){
                //说明错误码不为空，说明返回的结果有误，那么抛出异常
                throw new YyghException(ResultCodeEnum.FETCH_USERINFO_ERROR);//获取用户信息失败
            }
            //从json对象中获取用户信息
            String openid4Url = jsonObjectUserInfo.getString("openid");
            if(!openid.equals(openid4Url)){
                //从url中获取的用户id不等于从token中获取的用户id，则说明获取的用户id有误
                throw new YyghException(ResultCodeEnum.DATA_ERROR);//数据异常
            }
            String nickname = jsonObjectUserInfo.getString("nickname");
            //保存到数据库中
            userInfo.setOpenid(openid4Url);
            userInfo.setNickName(nickname);
            boolean save = userInfoService.save(userInfo);
        }

        //返回页面数据，生成token
        //有名字就展示名字，没有名字就展示昵称，没有昵称就展示手机号
        Map<String, Object> map = new HashMap<>();
        String name = userInfo.getPhone();
        if(StringUtils.hasText(userInfo.getNickName())){
            name = userInfo.getNickName();
        }
        if(StringUtils.hasText(userInfo.getName())){
            name = userInfo.getName();
        }
        map.put("name", name);
        if(!StringUtils.hasText(userInfo.getPhone())) {
            map.put("openid", userInfo.getOpenid());
        } else {
            map.put("openid", "");
        }

        try {
            name = URLEncoder.encode(name,"utf-8");
        } catch (UnsupportedEncodingException e) {
            new YyghException(ResultCodeEnum.URL_ENCODE_ERROR).printStackTrace();
        }
        String token = JwtHelper.createToken(userInfo.getId(),name);
        map.put("token", token);
        return "redirect:" + ConstantPropertiesUtil.YYGH_BASE_URL + "/weixin/callback?token="+map.get("token")+"&openid="+map.get("openid")+"&name="+name;
    }

}


































